<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Buffer in 2D and 3D</title>

<style>
  html, body {
    padding: 0;
    margin: 0;
    height: 100%;
  }
  #viewDiv{
    width: 100%;
    height: 100%;
  }
  #legend{
    position: absolute;
    background-color: white;
    bottom: 20px;
    left: 20px;
    z-index: 84;
    padding: 6px;
    opacity: 0.75;  
  }
</style>

<link rel="stylesheet" href="https://js.arcgis.com/4.0beta1/esri/css/esri.css">
<script src="https://js.arcgis.com/4.0beta1/"></script>

<script>
var map, view2d, point, wmPoint, geodesicBuffer, planarBuffer, sceneViewWatch, mapViewWatch;

require([
  "esri/Map",
  "esri/views/MapView",
  "esri/layers/GraphicsLayer",
  "esri/Graphic",
  "esri/geometry/SpatialReference",
  "esri/symbols/SimpleMarkerSymbol",
  "esri/symbols/SimpleLineSymbol",
  "esri/symbols/SimpleFillSymbol",
  "esri/geometry/geometryEngine",
  "esri/geometry/Point",
  "esri/geometry/support/webMercatorUtils",
  "dojo/domReady!"
],
function(
  Map,
  MapView,
  GraphicsLayer,
  Graphic,
  SpatialReference,
  SimpleMarkerSymbol,
  SimpleLineSymbol,
  SimpleFillSymbol,
  geometryEngine,
  Point,
  webMercatorUtils
) {

  map = new Map({
    basemap: "gray"
  });

  view2d = new MapView({
    container: "viewDiv",
    map: map,
    zoom: 3,
    center: [0,72]
  });

  /********************************************************************
  * Add two graphics layers to map: one for points, another for buffers
  ********************************************************************/

  var bufferLayer = new GraphicsLayer();
  var pointLayer = new GraphicsLayer();
  map.add([bufferLayer, pointLayer]);

  var pointSym = new SimpleMarkerSymbol({
    color: [0,0,0],
    size: 4
  });

  var geoSym = new SimpleFillSymbol({
    style: "none",
    outline: new SimpleLineSymbol({
      color: "green",
      width: 4
    })
  });
    
  var planarSym = new SimpleFillSymbol({
    style: "none",
    outline: new SimpleLineSymbol({
      color: [255,128,0],
      width: 4
    })
  });    

  /********************************************************************
  * Generate points every 10 degrees along Prime Meridian. Add to layer.
  * Buffer each point by 560km using GeometryEngine. Add buffers to map.
  ********************************************************************/

  addPoints();

  function addPoints(){
    for(var lat = -80; lat <= 80; lat+=10){
      point = new Point({
        x: 0,
        y: lat,
        spatialReference: new SpatialReference({wkid: 4326})
      });
      pointLayer.add(new Graphic({
        geometry: point,
        symbol: pointSym
      }));
        
      /********************************************************
      * Each point must be projected to Web Mercator in order to use
      * the buffer() function in GeometryEngine because buffer()
      * only takes projected geometries
      * ******************************************************/
      wmPoint = webMercatorUtils.geographicToWebMercator(point);    

      /********************************************************************
      * GeodesicBuffer calculates the true distance to buffer a point,
      * minimizing the distortion that exists when buffering points away
      * from a projection's line of tangency. This distortion is evident
      * in the 2D view of this application. This map uses a Web Mercator
      * spatial reference, which has a line of tangency at the equator.
      * Geodesic and planar buffers created on the equator have no distortion in their
      * shape or size. The further geodesic buffers are created away from the equator, the
      * more distorted they will be in their shape, but their size will remain accurate.
      *
      * If using a standard planar buffer, the shape of the buffers won't
      * distort, but their size and areas will be very distorted
      * (smaller than their true size) as they move away from the equator.
      ********************************************************************/
      geodesicBuffer = geometryEngine.geodesicBuffer(point, 560, "kilometers");
      bufferLayer.add(new Graphic({
        geometry: geodesicBuffer,
        symbol: geoSym
      }));
        
      planarBuffer = geometryEngine.buffer(wmPoint, 560, "kilometers");
      bufferLayer.add(new Graphic({
        geometry: planarBuffer,
        symbol: planarSym
      }));    
    }
  }
});
</script>
</head>

<body>
<div id="viewDiv">
  <div id="legend">Orange rings denote Euclidean buffers. 
      <br><br>Green rings denote geodesic buffers.</div>    
</div>
</body>

</html>
